package io.traveller.apiGateway.server.filter.pre;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import io.traveller.apiGateway.server.context.RequestContextHelper;
import io.traveller.apiGateway.server.filter.FilterType;
import io.traveller.auth.api.dto.AccountTokenDTO;
import io.traveller.auth.api.service.AuthService;
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
 * 处理accessToken的Filter
 * 1. 验证accessToken的有效性
 *      1.1 accessToken不存在
 *      1.2 accessToken过期
 *      1.3 accessToken禁用
 * 2. 若accessToken过期则使用refreshToken获取新的accessToken
 *      2.1 refreshToken不存在 TODO
 *      2.2 refreshToken过期 TODO
 *      2.3 refreshToken禁用 TODO
 *      TODO 第一期，不实现refresh_token功能
 *
 * Created by yunai on 16/9/16.
 */
public class PreGetAccessTokenFilter extends ZuulFilter {

    private final AuthService authService;

    protected ProxyRequestHelper helper = new ProxyRequestHelper();

    public PreGetAccessTokenFilter(AuthService authService) {
        this.authService = authService;
    }

    @Override
    public String filterType() {
        return FilterType.PRE;
    }

    @Override
    public int filterOrder() {
        return 200;
    }

    @Override
    public boolean shouldFilter() {
        // 依赖PreGetRouteExtFilter解析的accountSys
        RequestContext ctx = RequestContext.getCurrentContext();
        final Integer accountSys = RequestContextHelper.getAccountSys(ctx);
        if (accountSys == null) {
            return false;
        }
        // 依赖是否传递了accessToken
        final String accessToken = getAccessTokenFromRequest(ctx);
        return StringUtils.hasText(accessToken);
    }

    @Override
    public Object run() {
        // 获取accessToken信息
        RequestContext ctx = RequestContext.getCurrentContext();
        final Integer accountSys = RequestContextHelper.getAccountSys(ctx);
        final String accessToken = getAccessTokenFromRequest(ctx);
        Assert.notNull(accountSys, "accountSys 不能为空.");
        Assert.isTrue(StringUtils.hasText(accessToken), "accessToken 不能为空.");
        AccountTokenDTO accountTokenDTO = authService.findAccountToken(accountSys, accessToken);
        if (accountTokenDTO == null) { // TODO 不存在，则提示accessToken不存在
            RequestContextHelper.setResponse(ctx, 1, "token 不合法");
            return null;
        }
        // TODO 账号禁用
        if (accountTokenDTO.getExpireSeconds() <= 0) { // 账号已过期
            // TODO refresh_token
            return null;
        }
        // 设置ctx
        RequestContextHelper.setAccountId(ctx, accountTokenDTO.getAccountId());
        RequestContextHelper.setAccountType(ctx, accountTokenDTO.getAccountType());
        RequestContextHelper.setUserIdId(ctx, accountTokenDTO.getUserId());
        return accountTokenDTO;
    }

    /**
     * 从RequestContext中获取accessToken
     * 优先级：queryString > header > cookie
     *
     * @param ctx RequestContext
     * @return accessToken
     */
    // TODO 未实现完全
    private String getAccessTokenFromRequest(RequestContext ctx) {
        return RequestContextHelper.getRequestParameter("_access_token");
    }

}
